package net.sourceforge.jaad.aac.sbr;

import java.util.Arrays;

/**
 * This class is part of JAAD ( jaadec.sourceforge.net ) that is distributed
 * under the Public Domain license. Code changes provided by the JCodec project
 * are distributed under FreeBSD license.
 *
 * @author in-somnia
 */
class SynthesisFilterbank implements FilterbankTable {

    private static final float[][] qmf32_pre_twiddle = { { 0.999924701839145f, -0.012271538285720f },
            { 0.999322384588350f, -0.036807222941359f }, { 0.998118112900149f, -0.061320736302209f },
            { 0.996312612182778f, -0.085797312344440f }, { 0.993906970002356f, -0.110222207293883f },
            { 0.990902635427780f, -0.134580708507126f }, { 0.987301418157858f, -0.158858143333861f },
            { 0.983105487431216f, -0.183039887955141f }, { 0.978317370719628f, -0.207111376192219f },
            { 0.972939952205560f, -0.231058108280671f }, { 0.966976471044852f, -0.254865659604515f },
            { 0.960430519415566f, -0.278519689385053f }, { 0.953306040354194f, -0.302005949319228f },
            { 0.945607325380521f, -0.325310292162263f }, { 0.937339011912575f, -0.348418680249435f },
            { 0.928506080473216f, -0.371317193951838f }, { 0.919113851690058f, -0.393992040061048f },
            { 0.909167983090522f, -0.416429560097637f }, { 0.898674465693954f, -0.438616238538528f },
            { 0.887639620402854f, -0.460538710958240f }, { 0.876070094195407f, -0.482183772079123f },
            { 0.863972856121587f, -0.503538383725718f }, { 0.851355193105265f, -0.524589682678469f },
            { 0.838224705554838f, -0.545324988422046f }, { 0.824589302785025f, -0.565731810783613f },
            { 0.810457198252595f, -0.585797857456439f }, { 0.795836904608884f, -0.605511041404326f },
            { 0.780737228572094f, -0.624859488142386f }, { 0.765167265622459f, -0.643831542889791f },
            { 0.749136394523459f, -0.662415777590172f }, { 0.732654271672413f, -0.680600997795453f },
            { 0.715730825283819f, -0.698376249408973f } };

    private float[] v; // double ringbuffer
    private int v_index; // ringbuffer index
    private final int channels;

    public SynthesisFilterbank(int channels) {
        this.channels = channels;
        v = new float[2 * channels * 20];
        v_index = 0;
    }

    public void reset() {
        Arrays.fill(v, 0);
    }

    void sbr_qmf_synthesis_32(SBR sbr, float[][][] X, float[] output) {
        float[] x1 = new float[32], x2 = new float[32];
        float scale = 1.f / 64.f;
        int n, k, out = 0;
        int l;

        /* qmf subsample l */
        for (l = 0; l < sbr.numTimeSlotsRate; l++) {
            /* shift buffer v */
            /* buffer is not shifted, we are using a ringbuffer */
            // memmove(qmfs.v + 64, qmfs.v, (640-64)*sizeof(real_t));

            /* calculate 64 samples */
            /* complex pre-twiddle */
            for (k = 0; k < 32; k++) {
                x1[k] = (X[l][k][0] * qmf32_pre_twiddle[k][0]) - (X[l][k][1] * qmf32_pre_twiddle[k][1]);
                x2[k] = (X[l][k][1] * qmf32_pre_twiddle[k][0]) + (X[l][k][0] * qmf32_pre_twiddle[k][1]);

                x1[k] *= scale;
                x2[k] *= scale;
            }

            /* transform */
            DCT4_32(x1, x1);
            DST4_32(x2, x2);

            for (n = 0; n < 32; n++) {
                this.v[this.v_index + n] = this.v[this.v_index + 640 + n] = -x1[n] + x2[n];
                this.v[this.v_index + 63 - n] = this.v[this.v_index + 640 + 63 - n] = x1[n] + x2[n];
            }

            /* calculate 32 output samples and window */
            for (k = 0; k < 32; k++) {
                output[out++] = (this.v[this.v_index + k] * qmf_c[2 * k])
                        + (this.v[this.v_index + 96 + k] * qmf_c[64 + 2 * k])
                        + (this.v[this.v_index + 128 + k] * qmf_c[128 + 2 * k])
                        + (this.v[this.v_index + 224 + k] * qmf_c[192 + 2 * k])
                        + (this.v[this.v_index + 256 + k] * qmf_c[256 + 2 * k])
                        + (this.v[this.v_index + 352 + k] * qmf_c[320 + 2 * k])
                        + (this.v[this.v_index + 384 + k] * qmf_c[384 + 2 * k])
                        + (this.v[this.v_index + 480 + k] * qmf_c[448 + 2 * k])
                        + (this.v[this.v_index + 512 + k] * qmf_c[512 + 2 * k])
                        + (this.v[this.v_index + 608 + k] * qmf_c[576 + 2 * k]);
            }

            /* update ringbuffer index */
            this.v_index -= 64;
            if (this.v_index < 0)
                this.v_index = (640 - 64);
        }
    }

    void sbr_qmf_synthesis_64(SBR sbr, float[][][] X, float[] output) {
        float[] in_real1 = new float[32], in_imag1 = new float[32], out_real1 = new float[32],
                out_imag1 = new float[32];
        float[] in_real2 = new float[32], in_imag2 = new float[32], out_real2 = new float[32],
                out_imag2 = new float[32];
        float[][] pX;
        float scale = 1.f / 64.f;
        int n, k, out = 0;
        int l;

        /* qmf subsample l */
        for (l = 0; l < sbr.numTimeSlotsRate; l++) {
            /* shift buffer v */
            /* buffer is not shifted, we use double ringbuffer */
            // memmove(qmfs.v + 128, qmfs.v, (1280-128)*sizeof(real_t));

            /* calculate 128 samples */
            pX = X[l];

            in_imag1[31] = scale * pX[1][0];
            in_real1[0] = scale * pX[0][0];
            in_imag2[31] = scale * pX[63 - 1][1];
            in_real2[0] = scale * pX[63 - 0][1];
            for (k = 1; k < 31; k++) {
                in_imag1[31 - k] = scale * pX[2 * k + 1][0];
                in_real1[k] = scale * pX[2 * k][0];
                in_imag2[31 - k] = scale * pX[63 - (2 * k + 1)][1];
                in_real2[k] = scale * pX[63 - (2 * k)][1];
            }
            in_imag1[0] = scale * pX[63][0];
            in_real1[31] = scale * pX[62][0];
            in_imag2[0] = scale * pX[63 - 63][1];
            in_real2[31] = scale * pX[63 - 62][1];

            // dct4_kernel is DCT_IV without reordering which is done before and after FFT
            DCT.dct4_kernel(in_real1, in_imag1, out_real1, out_imag1);
            DCT.dct4_kernel(in_real2, in_imag2, out_real2, out_imag2);

            int pring_buffer_1 = v_index; // *v
            int pring_buffer_3 = pring_buffer_1 + 1280;
            // ptemp_1 = x1;
            // ptemp_2 = x2;

            for (n = 0; n < 32; n++) {
                // pring_buffer_3 and pring_buffer_4 are needed only for double ring buffer
                v[pring_buffer_1 + 2 * n] = v[pring_buffer_3 + 2 * n] = out_real2[n] - out_real1[n];
                v[pring_buffer_1 + 127 - 2 * n] = v[pring_buffer_3 + 127 - 2 * n] = out_real2[n] + out_real1[n];
                v[pring_buffer_1 + 2 * n + 1] = v[pring_buffer_3 + 2 * n + 1] = out_imag2[31 - n] + out_imag1[31 - n];
                v[pring_buffer_1 + 127 - (2 * n + 1)] = v[pring_buffer_3 + 127 - (2 * n + 1)] = out_imag2[31 - n]
                        - out_imag1[31 - n];
            }

            pring_buffer_1 = v_index; // *v

            /* calculate 64 output samples and window */
            for (k = 0; k < 64; k++) {
                output[out++] = (v[pring_buffer_1 + k + 0] * qmf_c[k + 0])
                        + (v[pring_buffer_1 + k + 192] * qmf_c[k + 64]) + (v[pring_buffer_1 + k + 256] * qmf_c[k + 128])
                        + (v[pring_buffer_1 + k + (256 + 192)] * qmf_c[k + 192])
                        + (v[pring_buffer_1 + k + 512] * qmf_c[k + 256])
                        + (v[pring_buffer_1 + k + (512 + 192)] * qmf_c[k + 320])
                        + (v[pring_buffer_1 + k + 768] * qmf_c[k + 384])
                        + (v[pring_buffer_1 + k + (768 + 192)] * qmf_c[k + 448])
                        + (v[pring_buffer_1 + k + 1024] * qmf_c[k + 512])
                        + (v[pring_buffer_1 + k + (1024 + 192)] * qmf_c[k + 576]);
            }

            /* update ringbuffer index */
            this.v_index -= 128;
            if (this.v_index < 0)
                this.v_index = (1280 - 128);
        }
    }

    private void DCT4_32(float[] y, float[] x) {
        float f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10;
        float f11, f12, f13, f14, f15, f16, f17, f18, f19, f20;
        float f21, f22, f23, f24, f25, f26, f27, f28, f29, f30;
        float f31, f32, f33, f34, f35, f36, f37, f38, f39, f40;
        float f41, f42, f43, f44, f45, f46, f47, f48, f49, f50;
        float f51, f52, f53, f54, f55, f56, f57, f58, f59, f60;
        float f61, f62, f63, f64, f65, f66, f67, f68, f69, f70;
        float f71, f72, f73, f74, f75, f76, f77, f78, f79, f80;
        float f81, f82, f83, f84, f85, f86, f87, f88, f89, f90;
        float f91, f92, f93, f94, f95, f96, f97, f98, f99, f100;
        float f101, f102, f103, f104, f105, f106, f107, f108, f109, f110;
        float f111, f112, f113, f114, f115, f116, f117, f118, f119, f120;
        float f121, f122, f123, f124, f125, f126, f127, f128, f129, f130;
        float f131, f132, f133, f134, f135, f136, f137, f138, f139, f140;
        float f141, f142, f143, f144, f145, f146, f147, f148, f149, f150;
        float f151, f152, f153, f154, f155, f156, f157, f158, f159, f160;
        float f161, f162, f163, f164, f165, f166, f167, f168, f169, f170;
        float f171, f172, f173, f174, f175, f176, f177, f178, f179, f180;
        float f181, f182, f183, f184, f185, f186, f187, f188, f189, f190;
        float f191, f192, f193, f194, f195, f196, f197, f198, f199, f200;
        float f201, f202, f203, f204, f205, f206, f207, f208, f209, f210;
        float f211, f212, f213, f214, f215, f216, f217, f218, f219, f220;
        float f221, f222, f223, f224, f225, f226, f227, f228, f229, f230;
        float f231, f232, f233, f234, f235, f236, f237, f238, f239, f240;
        float f241, f242, f243, f244, f245, f246, f247, f248, f249, f250;
        float f251, f252, f253, f254, f255, f256, f257, f258, f259, f260;
        float f261, f262, f263, f264, f265, f266, f267, f268, f269, f270;
        float f271, f272, f273, f274, f275, f276, f277, f278, f279, f280;
        float f281, f282, f283, f284, f285, f286, f287, f288, f289, f290;
        float f291, f292, f293, f294, f295, f296, f297, f298, f299, f300;
        float f301, f302, f303, f304, f305, f306, f307, f310, f311, f312;
        float f313, f316, f317, f318, f319, f322, f323, f324, f325, f328;
        float f329, f330, f331, f334, f335, f336, f337, f340, f341, f342;
        float f343, f346, f347, f348, f349, f352, f353, f354, f355, f358;
        float f359, f360, f361, f364, f365, f366, f367, f370, f371, f372;
        float f373, f376, f377, f378, f379, f382, f383, f384, f385, f388;
        float f389, f390, f391, f394, f395, f396, f397;

        f0 = x[15] - x[16];
        f1 = x[15] + x[16];
        f2 = (0.7071067811865476f * f1);
        f3 = (0.7071067811865476f * f0);
        f4 = x[8] - x[23];
        f5 = x[8] + x[23];
        f6 = (0.7071067811865476f * f5);
        f7 = (0.7071067811865476f * f4);
        f8 = x[12] - x[19];
        f9 = x[12] + x[19];
        f10 = (0.7071067811865476f * f9);
        f11 = (0.7071067811865476f * f8);
        f12 = x[11] - x[20];
        f13 = x[11] + x[20];
        f14 = (0.7071067811865476f * f13);
        f15 = (0.7071067811865476f * f12);
        f16 = x[14] - x[17];
        f17 = x[14] + x[17];
        f18 = (0.7071067811865476f * f17);
        f19 = (0.7071067811865476f * f16);
        f20 = x[9] - x[22];
        f21 = x[9] + x[22];
        f22 = (0.7071067811865476f * f21);
        f23 = (0.7071067811865476f * f20);
        f24 = x[13] - x[18];
        f25 = x[13] + x[18];
        f26 = (0.7071067811865476f * f25);
        f27 = (0.7071067811865476f * f24);
        f28 = x[10] - x[21];
        f29 = x[10] + x[21];
        f30 = (0.7071067811865476f * f29);
        f31 = (0.7071067811865476f * f28);
        f32 = x[0] - f2;
        f33 = x[0] + f2;
        f34 = x[31] - f3;
        f35 = x[31] + f3;
        f36 = x[7] - f6;
        f37 = x[7] + f6;
        f38 = x[24] - f7;
        f39 = x[24] + f7;
        f40 = x[3] - f10;
        f41 = x[3] + f10;
        f42 = x[28] - f11;
        f43 = x[28] + f11;
        f44 = x[4] - f14;
        f45 = x[4] + f14;
        f46 = x[27] - f15;
        f47 = x[27] + f15;
        f48 = x[1] - f18;
        f49 = x[1] + f18;
        f50 = x[30] - f19;
        f51 = x[30] + f19;
        f52 = x[6] - f22;
        f53 = x[6] + f22;
        f54 = x[25] - f23;
        f55 = x[25] + f23;
        f56 = x[2] - f26;
        f57 = x[2] + f26;
        f58 = x[29] - f27;
        f59 = x[29] + f27;
        f60 = x[5] - f30;
        f61 = x[5] + f30;
        f62 = x[26] - f31;
        f63 = x[26] + f31;
        f64 = f39 + f37;
        f65 = (-0.5411961001461969f * f39);
        f66 = (0.9238795325112867f * f64);
        f67 = (1.3065629648763766f * f37);
        f68 = f65 + f66;
        f69 = f67 - f66;
        f70 = f38 + f36;
        f71 = (1.3065629648763770f * f38);
        f72 = (-0.3826834323650904f * f70);
        f73 = (0.5411961001461961f * f36);
        f74 = f71 + f72;
        f75 = f73 - f72;
        f76 = f47 + f45;
        f77 = (-0.5411961001461969f * f47);
        f78 = (0.9238795325112867f * f76);
        f79 = (1.3065629648763766f * f45);
        f80 = f77 + f78;
        f81 = f79 - f78;
        f82 = f46 + f44;
        f83 = (1.3065629648763770f * f46);
        f84 = (-0.3826834323650904f * f82);
        f85 = (0.5411961001461961f * f44);
        f86 = f83 + f84;
        f87 = f85 - f84;
        f88 = f55 + f53;
        f89 = (-0.5411961001461969f * f55);
        f90 = (0.9238795325112867f * f88);
        f91 = (1.3065629648763766f * f53);
        f92 = f89 + f90;
        f93 = f91 - f90;
        f94 = f54 + f52;
        f95 = (1.3065629648763770f * f54);
        f96 = (-0.3826834323650904f * f94);
        f97 = (0.5411961001461961f * f52);
        f98 = f95 + f96;
        f99 = f97 - f96;
        f100 = f63 + f61;
        f101 = (-0.5411961001461969f * f63);
        f102 = (0.9238795325112867f * f100);
        f103 = (1.3065629648763766f * f61);
        f104 = f101 + f102;
        f105 = f103 - f102;
        f106 = f62 + f60;
        f107 = (1.3065629648763770f * f62);
        f108 = (-0.3826834323650904f * f106);
        f109 = (0.5411961001461961f * f60);
        f110 = f107 + f108;
        f111 = f109 - f108;
        f112 = f33 - f68;
        f113 = f33 + f68;
        f114 = f35 - f69;
        f115 = f35 + f69;
        f116 = f32 - f74;
        f117 = f32 + f74;
        f118 = f34 - f75;
        f119 = f34 + f75;
        f120 = f41 - f80;
        f121 = f41 + f80;
        f122 = f43 - f81;
        f123 = f43 + f81;
        f124 = f40 - f86;
        f125 = f40 + f86;
        f126 = f42 - f87;
        f127 = f42 + f87;
        f128 = f49 - f92;
        f129 = f49 + f92;
        f130 = f51 - f93;
        f131 = f51 + f93;
        f132 = f48 - f98;
        f133 = f48 + f98;
        f134 = f50 - f99;
        f135 = f50 + f99;
        f136 = f57 - f104;
        f137 = f57 + f104;
        f138 = f59 - f105;
        f139 = f59 + f105;
        f140 = f56 - f110;
        f141 = f56 + f110;
        f142 = f58 - f111;
        f143 = f58 + f111;
        f144 = f123 + f121;
        f145 = (-0.7856949583871021f * f123);
        f146 = (0.9807852804032304f * f144);
        f147 = (1.1758756024193588f * f121);
        f148 = f145 + f146;
        f149 = f147 - f146;
        f150 = f127 + f125;
        f151 = (0.2758993792829431f * f127);
        f152 = (0.5555702330196022f * f150);
        f153 = (1.3870398453221475f * f125);
        f154 = f151 + f152;
        f155 = f153 - f152;
        f156 = f122 + f120;
        f157 = (1.1758756024193591f * f122);
        f158 = (-0.1950903220161287f * f156);
        f159 = (0.7856949583871016f * f120);
        f160 = f157 + f158;
        f161 = f159 - f158;
        f162 = f126 + f124;
        f163 = (1.3870398453221473f * f126);
        f164 = (-0.8314696123025455f * f162);
        f165 = (-0.2758993792829436f * f124);
        f166 = f163 + f164;
        f167 = f165 - f164;
        f168 = f139 + f137;
        f169 = (-0.7856949583871021f * f139);
        f170 = (0.9807852804032304f * f168);
        f171 = (1.1758756024193588f * f137);
        f172 = f169 + f170;
        f173 = f171 - f170;
        f174 = f143 + f141;
        f175 = (0.2758993792829431f * f143);
        f176 = (0.5555702330196022f * f174);
        f177 = (1.3870398453221475f * f141);
        f178 = f175 + f176;
        f179 = f177 - f176;
        f180 = f138 + f136;
        f181 = (1.1758756024193591f * f138);
        f182 = (-0.1950903220161287f * f180);
        f183 = (0.7856949583871016f * f136);
        f184 = f181 + f182;
        f185 = f183 - f182;
        f186 = f142 + f140;
        f187 = (1.3870398453221473f * f142);
        f188 = (-0.8314696123025455f * f186);
        f189 = (-0.2758993792829436f * f140);
        f190 = f187 + f188;
        f191 = f189 - f188;
        f192 = f113 - f148;
        f193 = f113 + f148;
        f194 = f115 - f149;
        f195 = f115 + f149;
        f196 = f117 - f154;
        f197 = f117 + f154;
        f198 = f119 - f155;
        f199 = f119 + f155;
        f200 = f112 - f160;
        f201 = f112 + f160;
        f202 = f114 - f161;
        f203 = f114 + f161;
        f204 = f116 - f166;
        f205 = f116 + f166;
        f206 = f118 - f167;
        f207 = f118 + f167;
        f208 = f129 - f172;
        f209 = f129 + f172;
        f210 = f131 - f173;
        f211 = f131 + f173;
        f212 = f133 - f178;
        f213 = f133 + f178;
        f214 = f135 - f179;
        f215 = f135 + f179;
        f216 = f128 - f184;
        f217 = f128 + f184;
        f218 = f130 - f185;
        f219 = f130 + f185;
        f220 = f132 - f190;
        f221 = f132 + f190;
        f222 = f134 - f191;
        f223 = f134 + f191;
        f224 = f211 + f209;
        f225 = (-0.8971675863426361f * f211);
        f226 = (0.9951847266721968f * f224);
        f227 = (1.0932018670017576f * f209);
        f228 = f225 + f226;
        f229 = f227 - f226;
        f230 = f215 + f213;
        f231 = (-0.4105245275223571f * f215);
        f232 = (0.8819212643483549f * f230);
        f233 = (1.3533180011743529f * f213);
        f234 = f231 + f232;
        f235 = f233 - f232;
        f236 = f219 + f217;
        f237 = (0.1386171691990915f * f219);
        f238 = (0.6343932841636455f * f236);
        f239 = (1.4074037375263826f * f217);
        f240 = f237 + f238;
        f241 = f239 - f238;
        f242 = f223 + f221;
        f243 = (0.6666556584777466f * f223);
        f244 = (0.2902846772544623f * f242);
        f245 = (1.2472250129866711f * f221);
        f246 = f243 + f244;
        f247 = f245 - f244;
        f248 = f210 + f208;
        f249 = (1.0932018670017574f * f210);
        f250 = (-0.0980171403295605f * f248);
        f251 = (0.8971675863426364f * f208);
        f252 = f249 + f250;
        f253 = f251 - f250;
        f254 = f214 + f212;
        f255 = (1.3533180011743529f * f214);
        f256 = (-0.4713967368259979f * f254);
        f257 = (0.4105245275223569f * f212);
        f258 = f255 + f256;
        f259 = f257 - f256;
        f260 = f218 + f216;
        f261 = (1.4074037375263826f * f218);
        f262 = (-0.7730104533627369f * f260);
        f263 = (-0.1386171691990913f * f216);
        f264 = f261 + f262;
        f265 = f263 - f262;
        f266 = f222 + f220;
        f267 = (1.2472250129866711f * f222);
        f268 = (-0.9569403357322089f * f266);
        f269 = (-0.6666556584777469f * f220);
        f270 = f267 + f268;
        f271 = f269 - f268;
        f272 = f193 - f228;
        f273 = f193 + f228;
        f274 = f195 - f229;
        f275 = f195 + f229;
        f276 = f197 - f234;
        f277 = f197 + f234;
        f278 = f199 - f235;
        f279 = f199 + f235;
        f280 = f201 - f240;
        f281 = f201 + f240;
        f282 = f203 - f241;
        f283 = f203 + f241;
        f284 = f205 - f246;
        f285 = f205 + f246;
        f286 = f207 - f247;
        f287 = f207 + f247;
        f288 = f192 - f252;
        f289 = f192 + f252;
        f290 = f194 - f253;
        f291 = f194 + f253;
        f292 = f196 - f258;
        f293 = f196 + f258;
        f294 = f198 - f259;
        f295 = f198 + f259;
        f296 = f200 - f264;
        f297 = f200 + f264;
        f298 = f202 - f265;
        f299 = f202 + f265;
        f300 = f204 - f270;
        f301 = f204 + f270;
        f302 = f206 - f271;
        f303 = f206 + f271;
        f304 = f275 + f273;
        f305 = (-0.9751575901732920f * f275);
        f306 = (0.9996988186962043f * f304);
        f307 = (1.0242400472191164f * f273);
        y[0] = f305 + f306;
        y[31] = f307 - f306;
        f310 = f279 + f277;
        f311 = (-0.8700688593994936f * f279);
        f312 = (0.9924795345987100f * f310);
        f313 = (1.1148902097979263f * f277);
        y[2] = f311 + f312;
        y[29] = f313 - f312;
        f316 = f283 + f281;
        f317 = (-0.7566008898816587f * f283);
        f318 = (0.9757021300385286f * f316);
        f319 = (1.1948033701953984f * f281);
        y[4] = f317 + f318;
        y[27] = f319 - f318;
        f322 = f287 + f285;
        f323 = (-0.6358464401941451f * f287);
        f324 = (0.9495281805930367f * f322);
        f325 = (1.2632099209919283f * f285);
        y[6] = f323 + f324;
        y[25] = f325 - f324;
        f328 = f291 + f289;
        f329 = (-0.5089684416985408f * f291);
        f330 = (0.9142097557035307f * f328);
        f331 = (1.3194510697085207f * f289);
        y[8] = f329 + f330;
        y[23] = f331 - f330;
        f334 = f295 + f293;
        f335 = (-0.3771887988789273f * f295);
        f336 = (0.8700869911087114f * f334);
        f337 = (1.3629851833384954f * f293);
        y[10] = f335 + f336;
        y[21] = f337 - f336;
        f340 = f299 + f297;
        f341 = (-0.2417766217337384f * f299);
        f342 = (0.8175848131515837f * f340);
        f343 = (1.3933930045694289f * f297);
        y[12] = f341 + f342;
        y[19] = f343 - f342;
        f346 = f303 + f301;
        f347 = (-0.1040360035527077f * f303);
        f348 = (0.7572088465064845f * f346);
        f349 = (1.4103816894602612f * f301);
        y[14] = f347 + f348;
        y[17] = f349 - f348;
        f352 = f274 + f272;
        f353 = (0.0347065382144002f * f274);
        f354 = (0.6895405447370668f * f352);
        f355 = (1.4137876276885337f * f272);
        y[16] = f353 + f354;
        y[15] = f355 - f354;
        f358 = f278 + f276;
        f359 = (0.1731148370459795f * f278);
        f360 = (0.6152315905806268f * f358);
        f361 = (1.4035780182072330f * f276);
        y[18] = f359 + f360;
        y[13] = f361 - f360;
        f364 = f282 + f280;
        f365 = (0.3098559453626100f * f282);
        f366 = (0.5349976198870972f * f364);
        f367 = (1.3798511851368043f * f280);
        y[20] = f365 + f366;
        y[11] = f367 - f366;
        f370 = f286 + f284;
        f371 = (0.4436129715409088f * f286);
        f372 = (0.4496113296546065f * f370);
        f373 = (1.3428356308501219f * f284);
        y[22] = f371 + f372;
        y[9] = f373 - f372;
        f376 = f290 + f288;
        f377 = (0.5730977622997509f * f290);
        f378 = (0.3598950365349881f * f376);
        f379 = (1.2928878353697271f * f288);
        y[24] = f377 + f378;
        y[7] = f379 - f378;
        f382 = f294 + f292;
        f383 = (0.6970633083205415f * f294);
        f384 = (0.2667127574748984f * f382);
        f385 = (1.2304888232703382f * f292);
        y[26] = f383 + f384;
        y[5] = f385 - f384;
        f388 = f298 + f296;
        f389 = (0.8143157536286401f * f298);
        f390 = (0.1709618887603012f * f388);
        f391 = (1.1562395311492424f * f296);
        y[28] = f389 + f390;
        y[3] = f391 - f390;
        f394 = f302 + f300;
        f395 = (0.9237258930790228f * f302);
        f396 = (0.0735645635996674f * f394);
        f397 = (1.0708550202783576f * f300);
        y[30] = f395 + f396;
        y[1] = f397 - f396;
    }

    private void DST4_32(float[] y, float[] x) {
        float f0, f1, f2, f3, f4, f5, f6, f7, f8, f9;
        float f10, f11, f12, f13, f14, f15, f16, f17, f18, f19;
        float f20, f21, f22, f23, f24, f25, f26, f27, f28, f29;
        float f30, f31, f32, f33, f34, f35, f36, f37, f38, f39;
        float f40, f41, f42, f43, f44, f45, f46, f47, f48, f49;
        float f50, f51, f52, f53, f54, f55, f56, f57, f58, f59;
        float f60, f61, f62, f63, f64, f65, f66, f67, f68, f69;
        float f70, f71, f72, f73, f74, f75, f76, f77, f78, f79;
        float f80, f81, f82, f83, f84, f85, f86, f87, f88, f89;
        float f90, f91, f92, f93, f94, f95, f96, f97, f98, f99;
        float f100, f101, f102, f103, f104, f105, f106, f107, f108, f109;
        float f110, f111, f112, f113, f114, f115, f116, f117, f118, f119;
        float f120, f121, f122, f123, f124, f125, f126, f127, f128, f129;
        float f130, f131, f132, f133, f134, f135, f136, f137, f138, f139;
        float f140, f141, f142, f143, f144, f145, f146, f147, f148, f149;
        float f150, f151, f152, f153, f154, f155, f156, f157, f158, f159;
        float f160, f161, f162, f163, f164, f165, f166, f167, f168, f169;
        float f170, f171, f172, f173, f174, f175, f176, f177, f178, f179;
        float f180, f181, f182, f183, f184, f185, f186, f187, f188, f189;
        float f190, f191, f192, f193, f194, f195, f196, f197, f198, f199;
        float f200, f201, f202, f203, f204, f205, f206, f207, f208, f209;
        float f210, f211, f212, f213, f214, f215, f216, f217, f218, f219;
        float f220, f221, f222, f223, f224, f225, f226, f227, f228, f229;
        float f230, f231, f232, f233, f234, f235, f236, f237, f238, f239;
        float f240, f241, f242, f243, f244, f245, f246, f247, f248, f249;
        float f250, f251, f252, f253, f254, f255, f256, f257, f258, f259;
        float f260, f261, f262, f263, f264, f265, f266, f267, f268, f269;
        float f270, f271, f272, f273, f274, f275, f276, f277, f278, f279;
        float f280, f281, f282, f283, f284, f285, f286, f287, f288, f289;
        float f290, f291, f292, f293, f294, f295, f296, f297, f298, f299;
        float f300, f301, f302, f303, f304, f305, f306, f307, f308, f309;
        float f310, f311, f312, f313, f314, f315, f316, f317, f318, f319;
        float f320, f321, f322, f323, f324, f325, f326, f327, f328, f329;
        float f330, f331, f332, f333, f334, f335;

        f0 = x[0] - x[1];
        f1 = x[2] - x[1];
        f2 = x[2] - x[3];
        f3 = x[4] - x[3];
        f4 = x[4] - x[5];
        f5 = x[6] - x[5];
        f6 = x[6] - x[7];
        f7 = x[8] - x[7];
        f8 = x[8] - x[9];
        f9 = x[10] - x[9];
        f10 = x[10] - x[11];
        f11 = x[12] - x[11];
        f12 = x[12] - x[13];
        f13 = x[14] - x[13];
        f14 = x[14] - x[15];
        f15 = x[16] - x[15];
        f16 = x[16] - x[17];
        f17 = x[18] - x[17];
        f18 = x[18] - x[19];
        f19 = x[20] - x[19];
        f20 = x[20] - x[21];
        f21 = x[22] - x[21];
        f22 = x[22] - x[23];
        f23 = x[24] - x[23];
        f24 = x[24] - x[25];
        f25 = x[26] - x[25];
        f26 = x[26] - x[27];
        f27 = x[28] - x[27];
        f28 = x[28] - x[29];
        f29 = x[30] - x[29];
        f30 = x[30] - x[31];
        f31 = (0.7071067811865476f * f15);
        f32 = x[0] - f31;
        f33 = x[0] + f31;
        f34 = f7 + f23;
        f35 = (1.3065629648763766f * f7);
        f36 = (-0.9238795325112866f * f34);
        f37 = (-0.5411961001461967f * f23);
        f38 = f35 + f36;
        f39 = f37 - f36;
        f40 = f33 - f39;
        f41 = f33 + f39;
        f42 = f32 - f38;
        f43 = f32 + f38;
        f44 = f11 - f19;
        f45 = f11 + f19;
        f46 = (0.7071067811865476f * f45);
        f47 = f3 - f46;
        f48 = f3 + f46;
        f49 = (0.7071067811865476f * f44);
        f50 = f49 - f27;
        f51 = f49 + f27;
        f52 = f51 + f48;
        f53 = (-0.7856949583871021f * f51);
        f54 = (0.9807852804032304f * f52);
        f55 = (1.1758756024193588f * f48);
        f56 = f53 + f54;
        f57 = f55 - f54;
        f58 = f50 + f47;
        f59 = (-0.2758993792829430f * f50);
        f60 = (0.8314696123025452f * f58);
        f61 = (1.3870398453221475f * f47);
        f62 = f59 + f60;
        f63 = f61 - f60;
        f64 = f41 - f56;
        f65 = f41 + f56;
        f66 = f43 - f62;
        f67 = f43 + f62;
        f68 = f42 - f63;
        f69 = f42 + f63;
        f70 = f40 - f57;
        f71 = f40 + f57;
        f72 = f5 - f9;
        f73 = f5 + f9;
        f74 = f13 - f17;
        f75 = f13 + f17;
        f76 = f21 - f25;
        f77 = f21 + f25;
        f78 = (0.7071067811865476f * f75);
        f79 = f1 - f78;
        f80 = f1 + f78;
        f81 = f73 + f77;
        f82 = (1.3065629648763766f * f73);
        f83 = (-0.9238795325112866f * f81);
        f84 = (-0.5411961001461967f * f77);
        f85 = f82 + f83;
        f86 = f84 - f83;
        f87 = f80 - f86;
        f88 = f80 + f86;
        f89 = f79 - f85;
        f90 = f79 + f85;
        f91 = (0.7071067811865476f * f74);
        f92 = f29 - f91;
        f93 = f29 + f91;
        f94 = f76 + f72;
        f95 = (1.3065629648763766f * f76);
        f96 = (-0.9238795325112866f * f94);
        f97 = (-0.5411961001461967f * f72);
        f98 = f95 + f96;
        f99 = f97 - f96;
        f100 = f93 - f99;
        f101 = f93 + f99;
        f102 = f92 - f98;
        f103 = f92 + f98;
        f104 = f101 + f88;
        f105 = (-0.8971675863426361f * f101);
        f106 = (0.9951847266721968f * f104);
        f107 = (1.0932018670017576f * f88);
        f108 = f105 + f106;
        f109 = f107 - f106;
        f110 = f90 - f103;
        f111 = (-0.6666556584777466f * f103);
        f112 = (0.9569403357322089f * f110);
        f113 = (1.2472250129866713f * f90);
        f114 = f112 - f111;
        f115 = f113 - f112;
        f116 = f102 + f89;
        f117 = (-0.4105245275223571f * f102);
        f118 = (0.8819212643483549f * f116);
        f119 = (1.3533180011743529f * f89);
        f120 = f117 + f118;
        f121 = f119 - f118;
        f122 = f87 - f100;
        f123 = (-0.1386171691990915f * f100);
        f124 = (0.7730104533627370f * f122);
        f125 = (1.4074037375263826f * f87);
        f126 = f124 - f123;
        f127 = f125 - f124;
        f128 = f65 - f108;
        f129 = f65 + f108;
        f130 = f67 - f114;
        f131 = f67 + f114;
        f132 = f69 - f120;
        f133 = f69 + f120;
        f134 = f71 - f126;
        f135 = f71 + f126;
        f136 = f70 - f127;
        f137 = f70 + f127;
        f138 = f68 - f121;
        f139 = f68 + f121;
        f140 = f66 - f115;
        f141 = f66 + f115;
        f142 = f64 - f109;
        f143 = f64 + f109;
        f144 = f0 + f30;
        f145 = (1.0478631305325901f * f0);
        f146 = (-0.9987954562051724f * f144);
        f147 = (-0.9497277818777548f * f30);
        f148 = f145 + f146;
        f149 = f147 - f146;
        f150 = f4 + f26;
        f151 = (1.2130114330978077f * f4);
        f152 = (-0.9700312531945440f * f150);
        f153 = (-0.7270510732912803f * f26);
        f154 = f151 + f152;
        f155 = f153 - f152;
        f156 = f8 + f22;
        f157 = (1.3315443865537255f * f8);
        f158 = (-0.9039892931234433f * f156);
        f159 = (-0.4764341996931612f * f22);
        f160 = f157 + f158;
        f161 = f159 - f158;
        f162 = f12 + f18;
        f163 = (1.3989068359730781f * f12);
        f164 = (-0.8032075314806453f * f162);
        f165 = (-0.2075082269882124f * f18);
        f166 = f163 + f164;
        f167 = f165 - f164;
        f168 = f16 + f14;
        f169 = (1.4125100802019777f * f16);
        f170 = (-0.6715589548470187f * f168);
        f171 = (0.0693921705079402f * f14);
        f172 = f169 + f170;
        f173 = f171 - f170;
        f174 = f20 + f10;
        f175 = (1.3718313541934939f * f20);
        f176 = (-0.5141027441932219f * f174);
        f177 = (0.3436258658070501f * f10);
        f178 = f175 + f176;
        f179 = f177 - f176;
        f180 = f24 + f6;
        f181 = (1.2784339185752409f * f24);
        f182 = (-0.3368898533922200f * f180);
        f183 = (0.6046542117908008f * f6);
        f184 = f181 + f182;
        f185 = f183 - f182;
        f186 = f28 + f2;
        f187 = (1.1359069844201433f * f28);
        f188 = (-0.1467304744553624f * f186);
        f189 = (0.8424460355094185f * f2);
        f190 = f187 + f188;
        f191 = f189 - f188;
        f192 = f149 - f173;
        f193 = f149 + f173;
        f194 = f148 - f172;
        f195 = f148 + f172;
        f196 = f155 - f179;
        f197 = f155 + f179;
        f198 = f154 - f178;
        f199 = f154 + f178;
        f200 = f161 - f185;
        f201 = f161 + f185;
        f202 = f160 - f184;
        f203 = f160 + f184;
        f204 = f167 - f191;
        f205 = f167 + f191;
        f206 = f166 - f190;
        f207 = f166 + f190;
        f208 = f192 + f194;
        f209 = (1.1758756024193588f * f192);
        f210 = (-0.9807852804032304f * f208);
        f211 = (-0.7856949583871021f * f194);
        f212 = f209 + f210;
        f213 = f211 - f210;
        f214 = f196 + f198;
        f215 = (1.3870398453221475f * f196);
        f216 = (-0.5555702330196022f * f214);
        f217 = (0.2758993792829431f * f198);
        f218 = f215 + f216;
        f219 = f217 - f216;
        f220 = f200 + f202;
        f221 = (0.7856949583871022f * f200);
        f222 = (0.1950903220161283f * f220);
        f223 = (1.1758756024193586f * f202);
        f224 = f221 + f222;
        f225 = f223 - f222;
        f226 = f204 + f206;
        f227 = (-0.2758993792829430f * f204);
        f228 = (0.8314696123025452f * f226);
        f229 = (1.3870398453221475f * f206);
        f230 = f227 + f228;
        f231 = f229 - f228;
        f232 = f193 - f201;
        f233 = f193 + f201;
        f234 = f195 - f203;
        f235 = f195 + f203;
        f236 = f197 - f205;
        f237 = f197 + f205;
        f238 = f199 - f207;
        f239 = f199 + f207;
        f240 = f213 - f225;
        f241 = f213 + f225;
        f242 = f212 - f224;
        f243 = f212 + f224;
        f244 = f219 - f231;
        f245 = f219 + f231;
        f246 = f218 - f230;
        f247 = f218 + f230;
        f248 = f232 + f234;
        f249 = (1.3065629648763766f * f232);
        f250 = (-0.9238795325112866f * f248);
        f251 = (-0.5411961001461967f * f234);
        f252 = f249 + f250;
        f253 = f251 - f250;
        f254 = f236 + f238;
        f255 = (0.5411961001461969f * f236);
        f256 = (0.3826834323650898f * f254);
        f257 = (1.3065629648763766f * f238);
        f258 = f255 + f256;
        f259 = f257 - f256;
        f260 = f240 + f242;
        f261 = (1.3065629648763766f * f240);
        f262 = (-0.9238795325112866f * f260);
        f263 = (-0.5411961001461967f * f242);
        f264 = f261 + f262;
        f265 = f263 - f262;
        f266 = f244 + f246;
        f267 = (0.5411961001461969f * f244);
        f268 = (0.3826834323650898f * f266);
        f269 = (1.3065629648763766f * f246);
        f270 = f267 + f268;
        f271 = f269 - f268;
        f272 = f233 - f237;
        f273 = f233 + f237;
        f274 = f235 - f239;
        f275 = f235 + f239;
        f276 = f253 - f259;
        f277 = f253 + f259;
        f278 = f252 - f258;
        f279 = f252 + f258;
        f280 = f241 - f245;
        f281 = f241 + f245;
        f282 = f243 - f247;
        f283 = f243 + f247;
        f284 = f265 - f271;
        f285 = f265 + f271;
        f286 = f264 - f270;
        f287 = f264 + f270;
        f288 = f272 - f274;
        f289 = f272 + f274;
        f290 = (0.7071067811865474f * f288);
        f291 = (0.7071067811865474f * f289);
        f292 = f276 - f278;
        f293 = f276 + f278;
        f294 = (0.7071067811865474f * f292);
        f295 = (0.7071067811865474f * f293);
        f296 = f280 - f282;
        f297 = f280 + f282;
        f298 = (0.7071067811865474f * f296);
        f299 = (0.7071067811865474f * f297);
        f300 = f284 - f286;
        f301 = f284 + f286;
        f302 = (0.7071067811865474f * f300);
        f303 = (0.7071067811865474f * f301);
        f304 = f129 - f273;
        f305 = f129 + f273;
        f306 = f131 - f281;
        f307 = f131 + f281;
        f308 = f133 - f285;
        f309 = f133 + f285;
        f310 = f135 - f277;
        f311 = f135 + f277;
        f312 = f137 - f295;
        f313 = f137 + f295;
        f314 = f139 - f303;
        f315 = f139 + f303;
        f316 = f141 - f299;
        f317 = f141 + f299;
        f318 = f143 - f291;
        f319 = f143 + f291;
        f320 = f142 - f290;
        f321 = f142 + f290;
        f322 = f140 - f298;
        f323 = f140 + f298;
        f324 = f138 - f302;
        f325 = f138 + f302;
        f326 = f136 - f294;
        f327 = f136 + f294;
        f328 = f134 - f279;
        f329 = f134 + f279;
        f330 = f132 - f287;
        f331 = f132 + f287;
        f332 = f130 - f283;
        f333 = f130 + f283;
        f334 = f128 - f275;
        f335 = f128 + f275;
        y[31] = (0.5001506360206510f * f305);
        y[30] = (0.5013584524464084f * f307);
        y[29] = (0.5037887256810443f * f309);
        y[28] = (0.5074711720725553f * f311);
        y[27] = (0.5124514794082247f * f313);
        y[26] = (0.5187927131053328f * f315);
        y[25] = (0.5265773151542700f * f317);
        y[24] = (0.5359098169079920f * f319);
        y[23] = (0.5469204379855088f * f321);
        y[22] = (0.5597698129470802f * f323);
        y[21] = (0.5746551840326600f * f325);
        y[20] = (0.5918185358574165f * f327);
        y[19] = (0.6115573478825099f * f329);
        y[18] = (0.6342389366884031f * f331);
        y[17] = (0.6603198078137061f * f333);
        y[16] = (0.6903721282002123f * f335);
        y[15] = (0.7251205223771985f * f334);
        y[14] = (0.7654941649730891f * f332);
        y[13] = (0.8127020908144905f * f330);
        y[12] = (0.8683447152233481f * f328);
        y[11] = (0.9345835970364075f * f326);
        y[10] = (1.0144082649970547f * f324);
        y[9] = (1.1120716205797176f * f322);
        y[8] = (1.2338327379765710f * f320);
        y[7] = (1.3892939586328277f * f318);
        y[6] = (1.5939722833856311f * f316);
        y[5] = (1.8746759800084078f * f314);
        y[4] = (2.2820500680051619f * f312);
        y[3] = (2.9246284281582162f * f310);
        y[2] = (4.0846110781292477f * f308);
        y[1] = (6.7967507116736332f * f306);
        y[0] = (20.3738781672314530f * f304);
    }

}
